/**
 *  @file
 *  @brief   梁截面九节点网格剖分工具
 *  @author  duweixing
 *  @date    2024.07.14
 *  @version v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include <assert.h>

#include <vector>

#include "Utility/Algebra/Point.h"

#include "DataStructure/Common/Constant.h"
#include "DataStructure/Common/Out.h"
#include "DataStructure/Common/Real.h"
#include "DataStructure/Common/SGNamespace.h"

#include "../../Common/BeamSecPropCalculatorExport.h"
#include "SectionMesh.h"

SG_NAMESPACE_OPEN
namespace FEMSolver
{
    namespace Element
    {
        class BeamSecPropCalculator_DECLSPEC StandardSectionTool
        {
          public:
            /** @brief 对矩形生成九节点网格，生成网格的最后一列节点（位于平行于 z 轴的直线上）需要和已经生成好的网格块进行
             * merge。同时记录该矩形边界上的节点
             *  @param [in] point           矩形角点位置
             *  @param [in] a               矩形y轴方向边长，（a > 0 从左向右一列一列依次生成节点，a < 0 则从右向左一列一列生成节点）
             *  @param [in] b               矩形z轴方向边长，取值 b > 0
             *  @param [in] Na, Nb          矩形边界网格数
             *  @param [in] nodeId0, eleId0 用于网格中第一个节点和单元编号（创建单元和节点前，编号 + 1）
             *  @param [out] meshes         生成的网格
             *  @param [out] edgeNodes      位于矩形边上的节点
             */
            static void MeshRect (const SG::Algebra::Point&                         point,
                                  const SG::DataStructure::Common::Real             a,
                                  const SG::DataStructure::Common::Real             b,
                                  const int                                         Na,
                                  const int                                         Nb,
                                  const int                                         nodeId0,
                                  const int                                         eleId0,
                                  _OUT Meshes&          meshes,
                                  _OUT NodeSet&         edgeNodes);

            /** @brief 对矩形生成九节点网格，生成网格的最后一行节点（位于平行于 y 轴的直线上）需要和已经生成好的网格块进行 merge
             * 。同时记录该矩形边界上的节点
             *  @param [in] point           矩形角点位置
             *  @param [in] a               矩形y轴方向边长，取值 a > 0
             *  @param [in] b               矩形z轴方向边长，（b > 0 从下往上一行一行依次生成节点，b < 0 则从上往下一行一行依次生成节点）
             *  @param [in] Na, Nb          矩形边界网格数
             *  @param [in] nodeId0, eleId0 用于网格中第一个节点和单元编号（创建单元和节点前，编号 + 1）
             *  @param [out] meshes         生成的网格
             *  @param [out] edgeNodes      位于矩形边上的节点
             */
            static void MeshRect2 (const SG::Algebra::Point&                          point,
                                   const SG::DataStructure::Common::Real              a,
                                   const SG::DataStructure::Common::Real              b,
                                   const int                                          Na,
                                   const int                                          Nb,
                                   const int                                          nodeId0,
                                   const int                                          eleId0,
                                   _OUT Meshes&          meshes,
                                   _OUT NodeSet&         edgeNodes);

            /** @brief 新生成矩形网格块 `newMeshes` 合并到已有截面整体网格块 `meshes` 中
             *
             *  如果新生成网格块只存在最后若干节点重合的情况，则可直接调用本函数处理最后若干节点重合的情况；
             *  如果新生成网格块还存在最前若干节点重合的情况，则需要预先处理后，才能调用本函数处理最后若干节点重合的情况。
             *  @param [in] edgeNodes           截面整体边界节点集
             *  @param [in] numLastRepeatNodes  新生成网格块中重合节点的数量（最后 numLastRepeatNodes 个节点与已有截面网格中节点坐标重合）
             *  @param [in] newMeshes           新生成的块网格
             *  @param [in, out] meshes         截面的整体网格
             *  @param [in, out] nodeId, eleId  合并新生成网格块前后的节点、单元最大Id，用于确定下一次网格生成第一个节点、单元的编号
             *  @param [in] numFrontRepeatNodes 当 numFrontRepeatNodes > 0，`newMeshes` 中的前 numFrontRepeatNodes 个节点不需要加入 `meshes`
             * 的节点集中
             */
            static void Merge (const NodeSet& edgeNodes,
                               const int                                  numLastRepeatNodes,
                               const Meshes&  newMeshes,
                               _OUT  Meshes&  meshes,
                               _OUT int&                                  nodeId,
                               _OUT int&                                  eleId,
                               const int                                  numFrontRepeatNodes = 0);

            /** @brief
             * 处理最前若干节点重合，更新新生成网格块中节点的编号和单元的节点编号（重合节点的编号替换为已有节点编号，非重合节点的编号自减重合节点数）
             *  @param [in] edgeNodes           截面整体边界节点集
             *  @param [in] numFrontRepeatNodes 新生成网格块中重合节点的数量（最前 numFrontRepeatNodes 个节点与已有截面网格中节点坐标重合）
             *  @param [in, out] newMeshes      新生成网格块替换重复节点编号前、后的网格
             */
            static void Merge2 (const NodeSet& edgeNodes, 
                                const int numFrontRepeatNodes, 
                                _OUT  Meshes& newMeshes);

            /** @brief 将新生成网格块与已有截面网格块不重合边界的节点，加入到截面整体边界节点集中
             *  @param [in] newEdgeNodes       新生成网格块的边界节点
             *  @param [in] numLastRepeatNodes 新生成网格块中重合节点的数量（仅最后 numLastRepeatNodes 个节点与已有截面网格中节点坐标重合）
             *  @param [in, out] edgeNodes     加入新生成网格块边界节点前、后的截面整体边界节点集
             */
            static void UpdateEdgeNodes (const NodeSet& newEdgeNodes, const int numLastRepeatNodes, _OUT NodeSet& edgeNodes);
        };
    };  // end namespace Element
};  // end namespace FEMSolver
SG_NAMESPACE_CLOSE